﻿using Consul;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Syspetro.DepConsul
{
    /// <summary>
    /// Consul服务发现+负载均衡
    /// </summary>
    public abstract class AbstractConsulDispatcher
    {
        protected ConsulClientOption _ConsulClientOption = null;
        protected KeyValuePair<string, AgentService>[] _CurrentAgentServiceDictionary = null;

        public AbstractConsulDispatcher(IConfiguration configuration)
        {
            _ConsulClientOption = new ConsulClientOption();
            configuration.Bind("ConsulClient", _ConsulClientOption);
        }

        /// <summary>
        /// 负载均衡获取地址
        /// </summary>
        /// <param name="mappingUrl">Consul映射后的地址</param>
        /// <returns></returns>
        public string GetAddress(string mappingUrl)
        {
            Uri uri = new(mappingUrl);
            string serviceName = uri.Host;
            string addressPort = this.ChooseAddress(serviceName);
            return $"{uri.Scheme}://{addressPort}{uri.PathAndQuery}";
        }

        protected virtual string ChooseAddress(string serviceName)
        {
            ConsulClient client = new(c =>
            {
                c.Address = new Uri(_ConsulClientOption.Address);
                c.Datacenter = this._ConsulClientOption.Datacenter;
            });
            AgentService agentService = null;
            var response = client.Agent.Services().Result.Response;
            this._CurrentAgentServiceDictionary = response.Where(s => s.Value.Service.Equals(serviceName, StringComparison.OrdinalIgnoreCase)).ToArray();
            if(this._CurrentAgentServiceDictionary.Length == 0)
            {
                throw new Exception("没有可用服务，请检查'VerifyUserUrl'是否正确配置");
            }
            else{

                int index = this.GetIndex();
                agentService = this._CurrentAgentServiceDictionary[index].Value;
            }
            return $"{agentService.Address}:{agentService.Port}";
        }

        protected abstract int GetIndex();
    }
}
